package org.chaiyi.template.core.common.repository;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import org.chaiyi.template.core.common.exception.BaseErrorCode;
import org.chaiyi.template.core.common.exception.BusinessErrorType;
import org.chaiyi.template.core.common.util.asserts.Asserts;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Query;

import java.util.Arrays;
import java.util.List;

@Getter
public class QueryInfo {

    @Schema(title = "匹配条件")
    private String match;

    @Schema(title = "排序条件",example = "score asc;createTime desc;")
    private String sort;

    @Schema(title = "页码",description = "从零开始")
    private Integer page;

    @Schema(title = "页长")
    private Integer size;

    private interface Constant {
        String asc = "asc";
        String desc = "desc";
    }

    public Query pageQuery() {
        match = Asserts.isBlank(match) ? "{}" : match;
        Query query = new BasicQuery(match);
        query.with(pageRequest());
        return query;
    }

    public Query query() {
        match = Asserts.isBlank(match) ? "{}" : match;
        return new BasicQuery(match);
    }

    private PageRequest pageRequest() {
        page = null == page ? 0 : page;
        size = null == size ? 20 : size;
        return Asserts.isBlank(sort)
                ? PageRequest.of(page, size)
                : PageRequest.of(page, size, buildSort());
    }

    private Sort buildSort() {
        List<Sort.Order> orderList = Arrays.stream(sort.split(";"))
                .map(String::trim)
                .map(x -> {
                    String[] sortItem = x.split(" ");
                    BaseErrorCode.SORT_ITEM_EXCEPTION.throwIf(sortItem.length != 2, BusinessErrorType.TENSE);
                    return switch (sortItem[1]) {
                        case Constant.desc -> Sort.Order.desc(sortItem[0]);
                        case Constant.asc -> Sort.Order.asc(sortItem[0]);
                        default -> throw BaseErrorCode.SORT_ITEM_EXCEPTION.error(BusinessErrorType.TENSE);
                    };
                }).toList();
        return Sort.by(orderList);
    }

}
